package com.huilian.iotbox.mqtt.server.base.handler;

import com.huilian.iotbox.data.constants.IotConstant;
import com.huilian.iotbox.data.enums.IotBoxCmdEnum;
import com.huilian.iotbox.data.enums.ProductIdEnum;
import com.huilian.iotbox.data.po.DeviceItem;
import com.huilian.iotbox.data.vo.DeviceItemVo;
import com.huilian.iotbox.mqtt.server.base.handler.penetrate.AbstractStrategyServiceImpl;
import com.huilian.iotbox.mqtt.server.base.handler.penetrate.PenetrateHandlerStrategy;
import com.huilian.iotbox.mqtt.server.base.service.DeviceItemService;
import com.huilian.iotbox.mqtt.server.base.service.DeviceService;
import com.huilian.iotbox.data.enums.DeviceTypeEnum;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.utils.IotBoxUtil;
import com.huilian.iotbox.data.vo.DeviceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * PenetrateHandler
 * 23.2、服务器和外部设备数据进行透传（支付盒子to服务器）
 *
 * @Author mineChen
 * @Date 2021/8/30 上午 10:06
 */

@Service("messageHandleService26")
@Slf4j
public class PenetrateHandler extends AbstractStrategyServiceImpl implements MessageHandlerStrategy {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceItemService deviceItemService;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private Map<String, PenetrateHandlerStrategy> penetrateHandlerStrategyMap;

    @Override
    public void process(String content, String deviceNo, String productKey, Integer serviceProviderCode) throws Exception {
        log.info("进入 服务器和外部设备数据进行透传" + deviceNo);
        /**
         * AA1E0126AA1802CC01010000000000000000000000000001010100141EDDDD4EDD
         *
         * AA0402100214DD
         */
        log.info("接收 {} 到透传指令：{}", deviceNo, content);
        DeviceVo deviceVo = deviceService.findOneDeviceByDeviceNo(deviceNo);

        final int positionId = -1;

        DeviceItem deviceItemCondition = new DeviceItem();
        deviceItemCondition.setPositionId(positionId);
        deviceItemCondition.setDeviceId(deviceVo.getId());
        final DeviceItem deviceItem = deviceItemService.getDeviceItem(deviceItemCondition);
        deviceVo.setDeviceItem(deviceItem);

        String data = content.substring(8, content.length() - 4);
        final String start = data.substring(0, 2);
        final String end = data.substring(data.length() - 2);

        if (!StringUtils.isEmpty(deviceVo.getDeviceTypeId()) && DeviceTypeEnum.BATTERY_CAR_CHARGING_PILE.getCode().compareTo(deviceVo.getDeviceTypeId()) == 0) {
            /**
             * 电瓶车共享充电桩，这里的串口协议很奇怪
             * 发送数据： AA 04 15 00 07 16
             * 接受数据： 55 0C 15 01 07 00 E7 00 00 00 A0 00 0F 57
             */
            final String cmd = data.substring(4, 6);
            final String checkCode = data.substring(data.length() - 2);
            final String checkData = data.substring(2, data.length() - 2);
            final String newCheckCode = IotBoxUtil.checkcode_0007(checkData);
            if (!checkCode.equalsIgnoreCase(newCheckCode)) {
                log.error("{}_1_透传消息校验不通过{}: {}", deviceNo, DeviceTypeEnum.BATTERY_CAR_CHARGING_PILE.getCode(), data);
                return;
            }

            PenetrateHandlerStrategy penetrateHandlerStrategy = penetrateHandlerStrategyMap.get("penetrateHandlerService17_" + cmd);
            if (StringUtils.isEmpty(penetrateHandlerStrategy)) {
                log.error("{}_2_透传消息校验不通过{}，penetrateHandlerStrategy示例为null: {}", deviceNo, DeviceTypeEnum.BATTERY_CAR_CHARGING_PILE.getCode(), data);
                return;
            }
            penetrateHandlerStrategy.process(data, deviceNo, positionId);
            return;
        } else if (!StringUtils.isEmpty(deviceVo.getDeviceTypeId()) && DeviceTypeEnum.HAO_JI_LE_PERAMBULATOR.getCode().compareTo(deviceVo.getDeviceTypeId()) == 0) {
            /**
             * 好集乐儿童车
             *
             */
            final String cmd = data.substring(6, 8);
            final String checkCode = data.substring(data.length() - 4, data.length() - 2);
            final String checkData = data.substring(2, data.length() - 4);
            final String newCheckCode = IotBoxUtil.checkcode_0007(checkData);
            if (!checkCode.equalsIgnoreCase(newCheckCode)) {
                log.error("{}_3_透传消息校验不通过{}： {}", deviceNo, DeviceTypeEnum.HAO_JI_LE_PERAMBULATOR.getCode(), data);
                return;
            }

            final String serviceName = new StringBuffer("penetrateHandlerService")
                    .append(DeviceTypeEnum.HAO_JI_LE_PERAMBULATOR.getCode())
                    .append("_")
                    .append(cmd).toString();
            PenetrateHandlerStrategy penetrateHandlerStrategy = penetrateHandlerStrategyMap.get(serviceName);
            if (StringUtils.isEmpty(penetrateHandlerStrategy)) {
                log.error("{}_4_透传消息校验不通过{}，penetrateHandlerStrategy示例为null: {}", deviceNo, DeviceTypeEnum.HAO_JI_LE_PERAMBULATOR.getCode(), data);
                return;
            }
            penetrateHandlerStrategy.process(data, deviceNo, positionId);
            return;
        } else if (ProductIdEnum._87.getCode().equals(deviceVo.getProductId())) {
            /**
             * 同控娃娃机杜总专版
             *
             */
            final String cmd = data.substring(6, 8);
            final String checkCode = data.substring(data.length() - 4, data.length() - 2);
            final String checkData = data.substring(2, data.length() - 4);
            final String newCheckCode = IotBoxUtil.checkcode_0007(checkData);
            if (!checkCode.equalsIgnoreCase(newCheckCode)) {
                log.error("{}_7_透传消息校验不通过{}： {}", deviceNo, DeviceTypeEnum.CRANE_MACHINE.getCode(), data);
                errorLogCommonService.writerInfoErrorLog(String.format("%s_7_透传消息校验不通过：%s", deviceNo, DeviceTypeEnum.CRANE_MACHINE.getCode()), data);
                return;
            }

            final String serviceName = new StringBuffer("penetrateHandlerServiceDuZong")
                    .append(cmd).toString();
            PenetrateHandlerStrategy penetrateHandlerStrategy = penetrateHandlerStrategyMap.get(serviceName);
            if (IotBoxCmdEnum.AA03DD.getHexadecimal().equalsIgnoreCase(cmd)) {
                // 投币
                if (StringUtils.isEmpty(penetrateHandlerStrategy)) {
                    log.error("{}_8_透传消息校验不通过{}，penetrateHandlerStrategy示例为null: {}", deviceNo, DeviceTypeEnum.ARCADE_GAME.getCode(), data);
                    return;
                }
                penetrateHandlerStrategy.process(data, deviceNo, positionId);
                return;
            } else if (IotBoxCmdEnum.AA13DD.getHexadecimal().equalsIgnoreCase(cmd)) {
                // 账目上报
                if (StringUtils.isEmpty(penetrateHandlerStrategy)) {
                    log.error("{}_9_透传消息校验不通过{}，penetrateHandlerStrategy示例为null: {}", deviceNo, DeviceTypeEnum.ARCADE_GAME.getCode(), data);
                    return;
                }
                penetrateHandlerStrategy.process(data, deviceNo, positionId);
                return;
            }
        }

        if (!start.equalsIgnoreCase("AA") && !end.equalsIgnoreCase("DD")) {
            // 这里实现一些不规则的指令，如纸钞机的没有帧头帧尾
            /**
             * 示例一：ICT纸钞机
             * 波特率不对应：000000
             * 1元：818F40
             * 5元：818F41
             * 10元：818F42
             * 20元：818F43
             * 50元：818F44
             * 100元：818F45
             * 压仓成功：10
             * 异常：2F
             */


            log.info("透传内容：" + data);
            PenetrateHandlerStrategy penetrateHandlerStrategy = null;
            if (data.length() == 6 && "818f".equalsIgnoreCase(data.substring(0, 4))) {
                penetrateHandlerStrategy = penetrateHandlerStrategyMap.get("penetrateHandlerICTService818f");
            } else {
                penetrateHandlerStrategy = penetrateHandlerStrategyMap.get("penetrateHandlerICTService");
            }
            penetrateHandlerStrategy.process(data, deviceNo, positionId);
            return;
        }

        // 循环分解处理串口数据，防止沾包数据进入逻辑
        int i = 0;
        while (data.length() > 1) {

            if (i > 200) {
                break;
            }

            log.info("data:" + data);
            i++;
            log.info("第" + i + "次进入校验");
            // 帧头
            String prefix = data.substring(0, 2);
            if (!IotConstant.CONTENT_PREFIX.equalsIgnoreCase(prefix)) {
                log.info("递归循环_1,截取从" + i);
                data = data.substring(1);
                continue;
            }

            String lenHex = data.substring(2, 4);
            int length = IotBoxUtil.singleHex2Int(lenHex) * 2;
            if (length + 2 > data.length()) {
                log.info("递归循环_2,截取从" + i);
                data = data.substring(1);
                continue;
            }
            String ddd = data.substring(2, length + 2);
            String checkCodeHex = data.substring(length + 2, length + 4);

            // 帧尾
            String suffix = data.substring(length + 4, length + 6);

            int totalLength = prefix.length() + ddd.length() + checkCodeHex.length() + suffix.length();
            if (IotConstant.CONTENT_SUFFIX.equalsIgnoreCase(suffix) && IotBoxUtil.checkcode_0007(ddd).equalsIgnoreCase(checkCodeHex)) {
                log.info("OK");
                super.processingSerialPortData(data, deviceNo, deviceVo, null);
                if (data.substring(6, 8).equalsIgnoreCase("26")) {
                    log.error("{}_8_串口数据包: {}", deviceNo, data);
                    errorLogCommonService.writerInfoErrorLog(String.format("%s_8_串口数据包", deviceNo), data);
                }
                data = data.substring(totalLength);
            }
        }
    }
}
